#!/usr/bin/env python3
"""
基于JSON文件存储的智能规则引擎
支持动态加载和管理关键词、模式、权重

主要功能：
1. 从JSON文件加载规则（关键词、模式、权重、上下文）
2. 分析问题文本，匹配关键词和正则模式
3. 提取输入输出格式和约束条件
4. 生成解决方案模板和测试数据生成器
5. 支持动态添加/删除关键词
6. 提供统计信息和规则管理功能

作者: AI Assistant
版本: 2.0
更新: 优化了约束提取逻辑，添加了预编译模式系统
"""

import re
import json
import os
from typing import Dict, List, Any, Optional, Tuple
from dataclasses import dataclass

@dataclass
class ProblemAnalysis:
    """
    问题分析结果数据类
    
    属性:
        problem_type (str): 问题类型，如'addition', 'factorial'等
        input_format (Dict[str, Any]): 输入格式信息，包含类型、变量、约束条件
        output_format (Dict[str, Any]): 输出格式信息，包含类型、描述、操作、约束条件
        solution_template (str): 解决方案代码模板
        test_data_generator (str): 测试数据生成器名称
        confidence (float): 匹配置信度，0.0-1.0之间
        matched_keywords (List[str]): 匹配到的关键词列表
        matched_patterns (List[str]): 匹配到的正则模式列表
    """
    problem_type: str
    input_format: Dict[str, Any]
    output_format: Dict[str, Any]
    solution_template: str
    test_data_generator: str
    confidence: float
    matched_keywords: List[str]
    matched_patterns: List[str]

class JSONRuleEngine:
    """
    基于JSON文件的智能规则引擎
    
    这是项目的核心组件，负责：
    1. 加载和管理JSON规则文件
    2. 分析问题文本，识别问题类型
    3. 提取输入输出格式和约束条件
    4. 生成解决方案模板
    
    主要特性：
    - 支持关键词匹配和正则模式匹配
    - 预编译正则表达式，提升性能
    - 动态添加/删除规则
    - 完善的错误处理机制
    """
    
    def __init__(self, rules_dir: str = "rules"):
        """
        初始化规则引擎
        
        参数:
            rules_dir (str): 规则文件目录路径，默认为"rules"
            
        属性:
            rules_dir (str): 规则文件目录
            keywords_data (Dict): 关键词数据
            patterns_data (Dict): 正则模式数据
            weights_data (Dict): 权重数据
            contexts_data (Dict): 上下文数据
            compiled_patterns (Dict): 预编译的正则表达式
            keyword_index (Dict): 关键词索引，用于快速查找
            patterns (Dict): 预编译的约束提取模式
            compiled_patterns_cache (Dict): 模式缓存
        """
        self.rules_dir = rules_dir
        self.keywords_data = {}      # 存储关键词规则
        self.patterns_data = {}      # 存储正则模式规则
        self.weights_data = {}       # 存储关键词权重
        self.contexts_data = {}      # 存储上下文信息
        self.compiled_patterns = {}  # 存储预编译的正则表达式
        self.keyword_index = {}      # 关键词到模式的映射索引
        
        # 预编译常用正则表达式模式（性能优化）
        self._compile_patterns()
        
        # 加载所有规则文件
        self._load_all_rules()
        
        # 构建索引以提高查询效率
        self._build_indexes()
    
    def _compile_patterns(self):
        """
        预编译常用正则表达式模式
        
        为了提高性能，在初始化时预编译所有常用的正则表达式模式。
        这些模式用于约束条件提取，避免在每次调用时重复编译。
        
        模式分类：
        - range: 范围约束模式（如"1到100"）
        - length: 长度约束模式（如"长度≤1000"）
        - type: 类型约束模式（数字、字符串、数组）
        - character: 字符约束模式（字母、数字、字母数字）
        - output_type: 输出类型模式（字符串、整数、布尔等）
        """
        self.patterns = {
            # 范围约束模式 - 用于提取数值范围限制
            'range': [
                r'(\d+)\s*到\s*(\d+)',                    # "1到100"
                r'(\d+)\s*-\s*(\d+)',                     # "1-100"
                r'范围\s*(\d+)\s*-\s*(\d+)',              # "范围1-100"
                r'(\d+)\s*≤\s*.*\s*≤\s*(\d+)',           # "1≤n≤100"
                r'(\d+)\s*到\s*(\d+)\s*之间',             # "1到100之间"
                r'(\d+)\s*至\s*(\d+)',                    # "1至100"
                r'(\d+)\s*~\s*(\d+)',                     # "1~100"
                r'(\d+)\s*到\s*(\d+)\s*的整数',           # "1到100的整数"
            ],
            # 长度约束模式 - 用于提取字符串或数组长度限制
            'length': [
                r'长度\s*≤\s*(\d+)',                      # "长度≤1000"
                r'不超过\s*(\d+)\s*个字符',               # "不超过1000个字符"
                r'字符串长度\s*(\d+)',                    # "字符串长度1000"
                r'最多\s*(\d+)\s*个字符',                 # "最多1000个字符"
                r'长度\s*(\d+)',                          # "长度1000"
                r'(\d+)\s*个字符',                       # "1000个字符"
                r'(\d+)\s*个字母',                       # "1000个字母"
            ],
            # 类型约束模式 - 用于识别数据类型
            'type': {
                'number': [r'正整数', r'整数', r'自然数', r'数字', r'正数', r'非负整数', r'非零整数'],
                'string': [r'字符串', r'字符', r'文本', r'字母'],
                'array': [r'数组', r'列表', r'序列', r'集合']
            },
            # 字符约束模式 - 用于识别字符集限制
            'character': {
                'letters': r'只包含字母|字母字符|英文字母',
                'digits': r'只包含数字|数字字符',
                'alphanumeric': r'大小写字母|字母和数字'
            },
            # 输出类型模式 - 用于识别输出数据类型
            'output_type': {
                'string': r'输出.*字符串|返回.*字符串|打印.*字符串|输出.*字符',
                'array': r'输出.*数组|返回.*列表|输出.*序列|输出.*集合',
                'integer': r'输出.*整数|返回.*数字|输出.*数值|输出.*个数|输出.*结果|输出.*最大值|输出.*最小值',
                'boolean': r'输出.*布尔|返回.*真假|输出.*true|false|输出.*是.*否',
                'float': r'输出.*浮点|返回.*小数|输出.*实数|保留.*小数'
            }
        }
        
        # 预编译正则表达式，提升匹配性能
        self.compiled_patterns_cache = {}
        for category, patterns in self.patterns.items():
            if isinstance(patterns, list):
                # 直接编译模式列表
                self.compiled_patterns_cache[category] = [re.compile(p) for p in patterns]
            elif isinstance(patterns, dict):
                # 编译嵌套字典中的模式
                self.compiled_patterns_cache[category] = {}
                for subcategory, subpatterns in patterns.items():
                    if isinstance(subpatterns, list):
                        self.compiled_patterns_cache[category][subcategory] = [re.compile(p) for p in subpatterns]
                    else:
                        self.compiled_patterns_cache[category][subcategory] = re.compile(subpatterns)
    
    def _load_all_rules(self):
        """
        加载所有规则文件
        
        从rules目录加载以下JSON文件：
        - keywords.json: 关键词规则，包含模式名称和对应的关键词列表
        - patterns.json: 正则模式规则，包含模式名称和对应的正则表达式列表
        - weights.json: 权重规则，包含关键词及其权重值
        - contexts.json: 上下文规则，包含上下文信息
        
        如果文件不存在，会输出警告信息但不影响程序运行。
        """
        try:
            # 加载关键词文件 - 包含问题类型和对应的关键词
            keywords_file = os.path.join(self.rules_dir, "keywords.json")
            if os.path.exists(keywords_file):
                with open(keywords_file, 'r', encoding='utf-8') as f:
                    self.keywords_data = json.load(f)
                print(f"已加载关键词文件: {len(self.keywords_data.get('patterns', {}))} 个模式")
            else:
                print("关键词文件不存在")
            
            # 加载模式文件 - 包含正则表达式模式
            patterns_file = os.path.join(self.rules_dir, "patterns.json")
            if os.path.exists(patterns_file):
                with open(patterns_file, 'r', encoding='utf-8') as f:
                    self.patterns_data = json.load(f)
                print(f"已加载模式文件: {len(self.patterns_data.get('patterns', {}))} 个模式")
            else:
                print("模式文件不存在")
            
            # 加载权重文件 - 包含关键词权重信息
            weights_file = os.path.join(self.rules_dir, "weights.json")
            if os.path.exists(weights_file):
                with open(weights_file, 'r', encoding='utf-8') as f:
                    self.weights_data = json.load(f)
                print(f"已加载权重文件: {len(self.weights_data.get('weights', {}))} 个权重")
            else:
                print("权重文件不存在")
            
            # 加载上下文文件 - 包含上下文信息
            contexts_file = os.path.join(self.rules_dir, "contexts.json")
            if os.path.exists(contexts_file):
                with open(contexts_file, 'r', encoding='utf-8') as f:
                    self.contexts_data = json.load(f)
                print(f"已加载上下文文件: {len(self.contexts_data.get('contexts', {}))} 个上下文")
            else:
                print("上下文文件不存在")
                
        except Exception as e:
            print(f"加载规则文件时出错: {e}")
    
    def _build_indexes(self):
        """
        构建索引以提高查询效率
        
        构建两个主要索引：
        1. keyword_index: 关键词到模式名称的映射，用于快速查找包含某个关键词的所有模式
        2. compiled_patterns: 预编译的正则表达式，避免重复编译
        
        这些索引显著提升了问题分析时的查询性能。
        """
        # 构建关键词索引 - 建立关键词到模式名称的映射关系
        self.keyword_index = {}
        patterns = self.keywords_data.get('patterns', {})
        
        for pattern_name, pattern_info in patterns.items():
            keywords = pattern_info.get('keywords', [])
            for keyword in keywords:
                if keyword not in self.keyword_index:
                    self.keyword_index[keyword] = []
                self.keyword_index[keyword].append(pattern_name)
        
        # 预编译正则表达式 - 避免在每次匹配时重复编译
        self.compiled_patterns = {}
        patterns_data = self.patterns_data.get('patterns', {})
        
        for pattern_name, pattern_list in patterns_data.items():
            self.compiled_patterns[pattern_name] = []
            for pattern in pattern_list:
                try:
                    compiled = re.compile(pattern)
                    self.compiled_patterns[pattern_name].append(compiled)
                except re.error as e:
                    print(f"正则表达式编译失败: {pattern} - {e}")
    
    def reload_rules(self):
        """
        重新加载规则文件
        
        当规则文件被修改后，可以调用此方法重新加载所有规则文件。
        这会重新构建索引，确保使用最新的规则数据。
        
        使用场景：
        - 规则文件被外部修改
        - 动态添加了新的规则
        - 需要刷新规则缓存
        """
        print("重新加载规则文件...")
        self._load_all_rules()
        self._build_indexes()
        print("规则文件重新加载完成")
    
    def analyze_problem(self, problem_text: str) -> ProblemAnalysis:
        """
        分析问题并返回结果
        
        这是规则引擎的核心方法，通过以下步骤分析问题：
        1. 关键词匹配：在问题文本中查找预定义的关键词
        2. 正则模式匹配：使用正则表达式匹配问题模式
        3. 综合评分：结合关键词权重和模式优先级计算总分
        4. 选择最佳匹配：选择得分最高的模式作为问题类型
        5. 提取格式信息：分析输入输出格式和约束条件
        6. 生成解决方案：提供代码模板和测试生成器
        
        参数:
            problem_text (str): 问题描述文本
            
        返回:
            ProblemAnalysis: 包含完整分析结果的数据对象
        """
        problem_text_lower = problem_text.lower()
        
        # 1. 关键词匹配 - 计算每个模式的关键词匹配分数
        keyword_scores = {}
        matched_keywords = {}
        
        patterns = self.keywords_data.get('patterns', {})
        for pattern_name, pattern_info in patterns.items():
            score = 0
            matched_kw = []
            
            # 遍历该模式的所有关键词
            for keyword in pattern_info.get('keywords', []):
                if keyword.lower() in problem_text_lower:
                    # 获取关键词权重，默认为1
                    weight = self.weights_data.get('weights', {}).get(keyword, 1)
                    score += weight
                    matched_kw.append(keyword)
            
            keyword_scores[pattern_name] = score
            matched_keywords[pattern_name] = matched_kw
        
        # 2. 正则模式匹配 - 计算每个模式的正则匹配分数
        pattern_scores = {}
        matched_patterns = {}
        
        patterns_data = self.patterns_data.get('patterns', {})
        for pattern_name, pattern_list in patterns_data.items():
            score = 0
            matched_pat = []
            
            # 使用预编译的正则表达式进行匹配
            for compiled_pattern in self.compiled_patterns.get(pattern_name, []):
                if compiled_pattern.search(problem_text_lower):
                    # 使用模式优先级作为分数
                    priority = patterns.get(pattern_name, {}).get('priority', 5)
                    score += priority
                    matched_pat.append(compiled_pattern.pattern)
            
            pattern_scores[pattern_name] = score
            matched_patterns[pattern_name] = matched_pat
        
        # 3. 综合评分 - 合并关键词分数和正则模式分数
        total_scores = {}
        for pattern_name in patterns.keys():
            total_scores[pattern_name] = (
                keyword_scores.get(pattern_name, 0) + 
                pattern_scores.get(pattern_name, 0)
            )
        
        # 4. 选择最佳匹配 - 找到得分最高的模式
        if not total_scores:
            # 如果没有匹配到任何模式，返回未知类型
            return ProblemAnalysis(
                problem_type="unknown",
                input_format={},
                output_format={},
                solution_template="",
                test_data_generator="",
                confidence=0.0,
                matched_keywords=[],
                matched_patterns=[]
            )
        
        best_pattern = max(total_scores.items(), key=lambda x: x[1])
        best_pattern_name = best_pattern[0]
        best_score = best_pattern[1]
        
        # 计算置信度 - 基于得分计算匹配置信度
        max_possible_score = 50  # 假设最大可能分数
        confidence = min(best_score / max_possible_score, 1.0)
        
        # 返回完整的分析结果
        return ProblemAnalysis(
            problem_type=best_pattern_name,
            input_format=self._extract_input_format(problem_text),
            output_format=self._extract_output_format(problem_text),
            solution_template=self._get_solution_template(best_pattern_name),
            test_data_generator=self._get_test_generator(best_pattern_name),
            confidence=confidence,
            matched_keywords=matched_keywords.get(best_pattern_name, []),
            matched_patterns=matched_patterns.get(best_pattern_name, [])
        )
    
    def _extract_input_format(self, text: str) -> Dict[str, Any]:
        """
        提取输入格式和约束条件
        
        从问题文本中提取输入相关的信息，包括：
        1. 约束条件：范围、长度、类型、字符、整除等约束
        2. 变量信息：输入变量的名称
        3. 输入类型：根据约束条件确定整体输入类型
        
        参数:
            text (str): 问题描述文本
            
        返回:
            Dict[str, Any]: 包含输入格式信息的字典
                - type: 输入类型（string/integer/array/multiple）
                - description: 格式描述
                - variables: 变量列表
                - constraints: 约束条件列表
        """
        constraints = []
        variables = []
        
        # 1. 提取范围约束 - 如"1到100"、"范围1-100"
        constraints.extend(self._extract_range_constraints(text))
        
        # 2. 提取长度约束 - 如"长度≤1000"、"不超过1000个字符"
        constraints.extend(self._extract_length_constraints(text))
        
        # 3. 提取类型约束 - 如"正整数"、"字符串"、"数组"
        constraints.extend(self._extract_type_constraints(text))
        
        # 4. 提取字符约束 - 如"只包含字母"、"字母和数字"
        constraints.extend(self._extract_character_constraints(text))
        
        # 5. 提取整除约束 - 如"能被3整除"
        constraints.extend(self._extract_divisible_constraints(text))
        
        # 6. 提取变量信息 - 如"a和b"、"两个数"
        variables = self._extract_variables(text)
        
        # 7. 确定输入类型 - 根据约束条件和文本内容推断
        input_type = self._determine_input_type(text, constraints)
        
        return {
            "type": input_type,
            "description": f"从文本'{text[:50]}...'中提取的输入格式",
            "variables": variables,
            "constraints": constraints
        }
    
    def _extract_output_format(self, text: str) -> Dict[str, Any]:
        """
        提取输出格式信息
        
        从问题文本中提取输出相关的信息，包括：
        1. 输出类型：字符串、整数、布尔、浮点、数组等
        2. 输出描述：对输出内容的描述
        3. 输出约束：精度、范围、长度等约束条件
        4. 操作类型：加法、减法、查找、排序等操作
        
        参数:
            text (str): 问题描述文本
            
        返回:
            Dict[str, Any]: 包含输出格式信息的字典
                - type: 输出类型（string/integer/boolean/float/array/single）
                - description: 输出描述
                - operation: 操作类型
                - constraints: 输出约束条件列表
        """
        # 1. 提取输出类型 - 根据文本内容推断输出数据类型
        output_type = self._determine_output_type(text)
        
        # 2. 提取输出描述 - 分析输出内容的描述
        output_description = self._extract_output_description(text)
        
        # 3. 提取输出约束 - 如精度、范围、长度等约束
        output_constraints = self._extract_output_constraints(text)
        
        # 4. 确定操作类型 - 识别具体的操作类型
        operation = self._determine_operation_type(text)
        
        return {
            "type": output_type,
            "description": output_description,
            "operation": operation,
            "constraints": output_constraints
        }
    
    def _extract_range_constraints(self, text: str) -> List[Dict[str, Any]]:
        """
        提取范围约束条件
        
        从文本中提取数值范围限制，支持多种表达方式：
        - "1到100"、"1-100"、"范围1-100"
        - "1≤n≤100"、"1到100之间"
        - "1至100"、"1~100"、"1到100的整数"
        
        参数:
            text (str): 问题描述文本
            
        返回:
            List[Dict[str, Any]]: 范围约束列表，每个约束包含：
                - type: "range"
                - min: 最小值
                - max: 最大值
                - description: 约束描述
                - source: 匹配的原始文本
        """
        constraints = []
        
        try:
            # 使用预编译的范围模式进行匹配
            for pattern in self.compiled_patterns_cache['range']:
                matches = pattern.finditer(text)
                for match in matches:
                    try:
                        min_val = int(match.group(1))
                        max_val = int(match.group(2))
                        
                        # 验证范围合理性 - 确保最小值不大于最大值
                        if min_val <= max_val:
                            constraints.append({
                                "type": "range",
                                "min": min_val,
                                "max": max_val,
                                "description": f"范围{min_val}-{max_val}",
                                "source": match.group(0)
                            })
                    except (ValueError, IndexError) as e:
                        # 忽略无效的匹配，继续处理下一个
                        continue
        except Exception as e:
            print(f"提取范围约束时出错: {e}")
        
        return constraints
    
    def _extract_length_constraints(self, text: str) -> List[Dict[str, Any]]:
        """提取长度约束"""
        constraints = []
        
        for pattern in self.compiled_patterns_cache['length']:
            matches = pattern.finditer(text)
            for match in matches:
                constraints.append({
                    "type": "length",
                    "max": int(match.group(1)),
                    "description": f"长度不超过{match.group(1)}",
                    "source": match.group(0)
                })
        
        return constraints
    
    def _extract_type_constraints(self, text: str) -> List[Dict[str, Any]]:
        """提取类型约束"""
        constraints = []
        
        # 数字类型约束
        for pattern in self.compiled_patterns_cache['type']['number']:
            if pattern.search(text):
                constraints.append({
                    "type": "type",
                    "allowed": "integer",
                    "description": f"类型：{pattern.pattern}",
                    "source": pattern.pattern
                })
                break  # 只添加一次数字类型约束
        
        # 字符串类型约束
        for pattern in self.compiled_patterns_cache['type']['string']:
            if pattern.search(text):
                constraints.append({
                    "type": "type",
                    "allowed": "string",
                    "description": f"类型：{pattern.pattern}",
                    "source": pattern.pattern
                })
                break
        
        # 数组类型约束
        for pattern in self.compiled_patterns_cache['type']['array']:
            if pattern.search(text):
                constraints.append({
                    "type": "type",
                    "allowed": "array",
                    "description": f"类型：{pattern.pattern}",
                    "source": pattern.pattern
                })
                break
        
        return constraints
    
    def _extract_character_constraints(self, text: str) -> List[Dict[str, Any]]:
        """提取字符约束"""
        constraints = []
        
        if self.compiled_patterns_cache['character']['letters'].search(text):
            constraints.append({
                "type": "character",
                "allowed": "letters",
                "description": "只包含字母",
                "source": "字母约束"
            })
        
        if self.compiled_patterns_cache['character']['digits'].search(text):
            constraints.append({
                "type": "character",
                "allowed": "digits",
                "description": "只包含数字",
                "source": "数字约束"
            })
        
        if self.compiled_patterns_cache['character']['alphanumeric'].search(text):
            constraints.append({
                "type": "character",
                "allowed": "alphanumeric",
                "description": "包含字母和数字",
                "source": "字母数字约束"
            })
        
        return constraints
    
    def _extract_constraints_generic(self, text: str, constraint_type: str, patterns: List[re.Pattern]) -> List[Dict[str, Any]]:
        """通用的约束提取方法"""
        constraints = []
        
        try:
            for pattern in patterns:
                matches = pattern.finditer(text)
                for match in matches:
                    try:
                        constraint = self._create_constraint_from_match(constraint_type, match)
                        if constraint:
                            constraints.append(constraint)
                    except Exception as e:
                        # 忽略无效的匹配
                        continue
        except Exception as e:
            print(f"提取{constraint_type}约束时出错: {e}")
        
        return constraints
    
    def _create_constraint_from_match(self, constraint_type: str, match: re.Match) -> Optional[Dict[str, Any]]:
        """根据匹配结果创建约束对象"""
        try:
            if constraint_type == "range":
                min_val = int(match.group(1))
                max_val = int(match.group(2))
                if min_val <= max_val:
                    return {
                        "type": "range",
                        "min": min_val,
                        "max": max_val,
                        "description": f"范围{min_val}-{max_val}",
                        "source": match.group(0)
                    }
            elif constraint_type == "length":
                max_val = int(match.group(1))
                if max_val > 0:
                    return {
                        "type": "length",
                        "max": max_val,
                        "description": f"长度不超过{max_val}",
                        "source": match.group(0)
                    }
            elif constraint_type == "divisible":
                divisor = int(match.group(1))
                if divisor > 0:
                    return {
                        "type": "divisible",
                        "by": divisor,
                        "description": f"能被{divisor}整除",
                        "source": match.group(0)
                    }
        except (ValueError, IndexError):
            pass
        
        return None
    
    def _extract_divisible_constraints(self, text: str) -> List[Dict[str, Any]]:
        """提取整除约束"""
        pattern = re.compile(r'能被\s*(\d+)\s*整除')
        return self._extract_constraints_generic(text, "divisible", [pattern])
    
    def _extract_variables(self, text: str) -> List[str]:
        """提取变量信息"""
        variables = []
        
        # 常见的变量模式
        variable_patterns = [
            r'(\w+)\s*和\s*(\w+)',                    # "a和b"
            r'两个\s*(\w+)',                          # "两个数"
            r'(\w+)\s*,\s*(\w+)',                    # "a,b"
            r'(\w+)\s*与\s*(\w+)',                   # "a与b"
        ]
        
        for pattern in variable_patterns:
            matches = re.finditer(pattern, text)
            for match in matches:
                if len(match.groups()) == 2:
                    var1, var2 = match.groups()
                    if var1 not in variables:
                        variables.append(var1)
                    if var2 not in variables:
                        variables.append(var2)
                elif len(match.groups()) == 1:
                    var = match.group(1)
                    if var not in variables:
                        variables.append(var)
        
        # 如果没有找到变量，使用默认值
        if not variables:
            variables = ["a", "b"]
        
        return variables
    
    def _determine_input_type(self, text: str, constraints: List[Dict]) -> str:
        """确定输入类型"""
        # 根据约束条件确定输入类型
        for constraint in constraints:
            if constraint.get("type") == "type":
                allowed_type = constraint.get("allowed")
                if allowed_type == "string":
                    return "string"
                elif allowed_type == "array":
                    return "array"
                elif allowed_type == "integer":
                    return "integer"
        
        # 根据文本内容推断
        if re.search(r'字符串|字符|文本', text):
            return "string"
        elif re.search(r'数组|列表|序列', text):
            return "array"
        elif re.search(r'数|整数|数字', text):
            return "integer"
        else:
            return "multiple"  # 默认多输入
    
    def _determine_output_type(self, text: str) -> str:
        """确定输出类型"""
        # 根据预编译的模式确定输出类型
        for output_type, pattern in self.compiled_patterns_cache['output_type'].items():
            if pattern.search(text):
                return output_type
        
        return "single"  # 默认单输出
    
    def _extract_output_description(self, text: str) -> str:
        """提取输出描述"""
        # 常见的输出描述模式
        output_patterns = [
            r'输出(.+?)(?:，|。|$)',                    # "输出..."
            r'返回(.+?)(?:，|。|$)',                    # "返回..."
            r'打印(.+?)(?:，|。|$)',                    # "打印..."
            r'显示(.+?)(?:，|。|$)',                    # "显示..."
            r'计算(.+?)(?:，|。|$)',                    # "计算..."
            r'求(.+?)(?:，|。|$)',                      # "求..."
            r'统计(.+?)(?:，|。|$)',                    # "统计..."
        ]
        
        for pattern in output_patterns:
            match = re.search(pattern, text)
            if match:
                description = match.group(1).strip()
                # 清理描述文本
                description = re.sub(r'的.*$', '', description)  # 去掉"的..."
                description = re.sub(r'^.*是', '', description)  # 去掉"...是"
                return f"输出{description}"
        
        return "计算结果"
    
    def _extract_output_constraints(self, text: str) -> List[Dict[str, Any]]:
        """提取输出约束"""
        constraints = []
        
        # 输出格式约束
        format_patterns = [
            r'输出格式.*?(\d+)\s*位',                    # "输出格式3位"
            r'保留(\d+)\s*位小数',                      # "保留2位小数"
            r'精确到(\d+)\s*位',                       # "精确到2位"
            r'四舍五入.*?(\d+)\s*位',                  # "四舍五入到2位"
        ]
        
        for pattern in format_patterns:
            match = re.search(pattern, text)
            if match:
                precision = int(match.group(1))
                constraints.append({
                    "type": "precision",
                    "value": precision,
                    "description": f"精度{precision}位",
                    "source": match.group(0)
                })
        
        # 输出范围约束
        range_patterns = [
            r'输出.*?(\d+)\s*到\s*(\d+)',              # "输出1到100"
            r'结果.*?(\d+)\s*-\s*(\d+)',               # "结果1-100"
            r'范围.*?(\d+)\s*到\s*(\d+)',             # "范围1到100"
        ]
        
        for pattern in range_patterns:
            match = re.search(pattern, text)
            if match:
                constraints.append({
                    "type": "range",
                    "min": int(match.group(1)),
                    "max": int(match.group(2)),
                    "description": f"输出范围{match.group(1)}-{match.group(2)}",
                    "source": match.group(0)
                })
        
        # 输出长度约束
        length_patterns = [
            r'输出.*?长度.*?(\d+)',                     # "输出长度100"
            r'最多.*?(\d+)\s*个字符',                  # "最多100个字符"
            r'不超过.*?(\d+)\s*个字符',                # "不超过100个字符"
        ]
        
        for pattern in length_patterns:
            match = re.search(pattern, text)
            if match:
                constraints.append({
                    "type": "length",
                    "max": int(match.group(1)),
                    "description": f"输出长度不超过{match.group(1)}",
                    "source": match.group(0)
                })
        
        return constraints
    
    def _determine_operation_type(self, text: str) -> str:
        """确定操作类型"""
        # 根据文本内容确定操作类型
        operation_patterns = [
            (r'加法|相加|求和|和', 'addition'),
            (r'减法|相减|求差|差', 'subtraction'),
            (r'乘法|相乘|求积|积', 'multiplication'),
            (r'除法|相除|求商|商', 'division'),
            (r'阶乘|!', 'factorial'),
            (r'平方|二次方', 'square'),
            (r'立方|三次方', 'cube'),
            (r'开方|根号', 'sqrt'),
            (r'最大值|最大', 'max'),
            (r'最小值|最小', 'min'),
            (r'平均值|平均', 'average'),
            (r'排序|升序|降序', 'sort'),
            (r'反转|逆序|倒序', 'reverse'),
            (r'回文|palindrome', 'palindrome'),
            (r'质数|素数|prime', 'prime'),
            (r'斐波那契|fibonacci', 'fibonacci'),
            (r'最大公约数|gcd', 'gcd'),
            (r'最小公倍数|lcm', 'lcm'),
            (r'统计|计数|count', 'count'),
            (r'查找|搜索|search', 'search'),
        ]
        
        for pattern, operation in operation_patterns:
            if re.search(pattern, text):
                return operation
        
        return "unknown"
    
    def _get_solution_template(self, pattern_name: str) -> str:
        """获取解决方案模板"""
        templates = {
            "addition": "def solution(a, b):\n    return a + b",
            "subtraction": "def solution(a, b):\n    return a - b",
            "multiplication": "def solution(a, b):\n    return a * b",
            "division": "def solution(a, b):\n    return a / b if b != 0 else 0",
            "factorial": "def solution(n):\n    if n <= 1:\n        return 1\n    return n * solution(n-1)",
            "string_char_count": "def solution(s):\n    return sum(1 for c in s if c.isalpha())",
            "max_value": "def solution(arr):\n    return max(arr)",
            "min_value": "def solution(arr):\n    return min(arr)"
        }
        return templates.get(pattern_name, "def solution():\n    pass")
    
    def _get_test_generator(self, pattern_name: str) -> str:
        """获取测试数据生成器"""
        generators = {
            "addition": "generate_addition_tests",
            "subtraction": "generate_subtraction_tests",
            "multiplication": "generate_multiplication_tests",
            "division": "generate_division_tests",
            "factorial": "generate_factorial_tests",
            "string_char_count": "generate_string_tests",
            "max_value": "generate_array_tests",
            "min_value": "generate_array_tests"
        }
        return generators.get(pattern_name, "generate_default_tests")
    
    def add_keyword(self, pattern_name: str, keyword: str, weight: int = 5):
        """动态添加关键词"""
        if pattern_name not in self.keywords_data.get('patterns', {}):
            print(f"模式 '{pattern_name}' 不存在")
            return False
        
        # 添加到内存
        self.keywords_data['patterns'][pattern_name]['keywords'].append(keyword)
        self.weights_data['weights'][keyword] = weight
        
        # 更新索引
        if keyword not in self.keyword_index:
            self.keyword_index[keyword] = []
        self.keyword_index[keyword].append(pattern_name)
        
        print(f"已添加关键词 '{keyword}' 到模式 '{pattern_name}'")
        return True
    
    def remove_keyword(self, pattern_name: str, keyword: str):
        """动态删除关键词"""
        if pattern_name not in self.keywords_data.get('patterns', {}):
            print(f"模式 '{pattern_name}' 不存在")
            return False
        
        # 从内存删除
        if keyword in self.keywords_data['patterns'][pattern_name]['keywords']:
            self.keywords_data['patterns'][pattern_name]['keywords'].remove(keyword)
        
        if keyword in self.weights_data['weights']:
            del self.weights_data['weights'][keyword]
        
        if keyword in self.keyword_index:
            if pattern_name in self.keyword_index[keyword]:
                self.keyword_index[keyword].remove(pattern_name)
            if not self.keyword_index[keyword]:
                del self.keyword_index[keyword]
        
        print(f"已删除关键词 '{keyword}' 从模式 '{pattern_name}'")
        return True
    
    def save_rules(self):
        """保存规则到文件"""
        try:
            # 保存关键词
            keywords_file = os.path.join(self.rules_dir, "keywords.json")
            with open(keywords_file, 'w', encoding='utf-8') as f:
                json.dump(self.keywords_data, f, ensure_ascii=False, indent=4)
            
            # 保存权重
            weights_file = os.path.join(self.rules_dir, "weights.json")
            with open(weights_file, 'w', encoding='utf-8') as f:
                json.dump(self.weights_data, f, ensure_ascii=False, indent=4)
            
            print("规则已保存到文件")
            return True
        except Exception as e:
            print(f"保存规则时出错: {e}")
            return False
    
    def get_statistics(self) -> Dict[str, Any]:
        """获取统计信息"""
        patterns = self.keywords_data.get('patterns', {})
        weights = self.weights_data.get('weights', {})
        
        stats = {
            "total_patterns": len(patterns),
            "total_keywords": len(weights),
            "patterns_by_category": {},
            "weight_distribution": {
                "high": 0,
                "medium": 0,
                "low": 0
            }
        }
        
        # 按类别统计
        for pattern_name, pattern_info in patterns.items():
            category = pattern_info.get('category', 'unknown')
            if category not in stats["patterns_by_category"]:
                stats["patterns_by_category"][category] = 0
            stats["patterns_by_category"][category] += 1
        
        # 权重分布统计
        for keyword, weight in weights.items():
            if weight >= 8:
                stats["weight_distribution"]["high"] += 1
            elif weight >= 5:
                stats["weight_distribution"]["medium"] += 1
            else:
                stats["weight_distribution"]["low"] += 1
        
        return stats
    
    def find_keywords_by_pattern(self, pattern_name: str) -> List[str]:
        """根据模式名称查找关键词"""
        patterns = self.keywords_data.get('patterns', {})
        if pattern_name in patterns:
            return patterns[pattern_name].get('keywords', [])
        return []
    
    def find_patterns_by_keyword(self, keyword: str) -> List[str]:
        """根据关键词查找相关模式"""
        return self.keyword_index.get(keyword, [])
    
    def extract_keywords_from_text(self, text: str) -> List[Tuple[str, str, int]]:
        """从文本中提取关键词"""
        text_lower = text.lower()
        extracted = []
        
        for keyword, patterns in self.keyword_index.items():
            if keyword.lower() in text_lower:
                weight = self.weights_data.get('weights', {}).get(keyword, 1)
                for pattern_name in patterns:
                    extracted.append((keyword, pattern_name, weight))
        
        return extracted

def demo_constraint_extraction():
    """
    演示约束条件提取功能
    
    这个函数展示了规则引擎的约束条件提取能力，包括：
    1. 输入格式提取：类型、变量、约束条件
    2. 输出格式提取：类型、描述、操作、约束条件
    3. 各种约束类型的识别：范围、长度、类型、字符、整除等
    
    测试用例涵盖了常见的编程问题类型，验证提取功能的准确性。
    """
    print("=" * 80)
    print("输入格式和输出格式提取功能演示")
    print("=" * 80)
    
    # 创建引擎实例
    engine = JSONRuleEngine()
    
    # 测试输入和输出格式提取 - 涵盖各种约束类型的问题
    test_problems = [
        "计算两个正整数的和，范围1到100，输出结果",                    # 范围约束 + 类型约束
        "统计字符串中字母出现次数，长度不超过1000个字符，输出整数",        # 长度约束 + 类型约束
        "找到数组中的最大值，数组长度1到50，输出最大值",                # 范围约束 + 长度约束 + 类型约束
        "判断一个数是否为质数，范围2到1000，输出true或false",          # 范围约束 + 布尔输出
        "计算能被3整除的数的个数，范围1到100，输出个数",              # 范围约束 + 整除约束
        "反转字符串，只包含大小写字母，输出反转后的字符串"              # 字符约束 + 字符串输出
    ]
    
    for i, problem in enumerate(test_problems, 1):
        print(f"\n问题 {i}: {problem}")
        print("-" * 60)
        
        # 提取输入格式和约束条件
        input_format = engine._extract_input_format(problem)
        output_format = engine._extract_output_format(problem)
        
        # 显示输入格式信息
        print(f"输入格式:")
        print(f"  类型: {input_format['type']}")
        print(f"  变量: {input_format['variables']}")
        print(f"  约束条件:")
        
        if input_format['constraints']:
            for j, constraint in enumerate(input_format['constraints'], 1):
                print(f"    {j}. {constraint['description']} ({constraint['type']})")
                if 'source' in constraint:
                    print(f"        来源: '{constraint['source']}'")
        else:
            print("    无约束条件")
        
        # 显示输出格式信息
        print(f"\n输出格式:")
        print(f"  类型: {output_format['type']}")
        print(f"  描述: {output_format['description']}")
        print(f"  操作: {output_format['operation']}")
        print(f"  约束条件:")
        
        if output_format['constraints']:
            for j, constraint in enumerate(output_format['constraints'], 1):
                print(f"    {j}. {constraint['description']} ({constraint['type']})")
                if 'source' in constraint:
                    print(f"        来源: '{constraint['source']}'")
        else:
            print("    无约束条件")
    
    print("\n" + "=" * 80)
    print("输出格式提取详细测试")
    print("=" * 80)
    
    # 详细测试输出格式提取 - 验证各种输出类型的识别
    output_tests = [
        ("输出类型测试", "计算两个数的和，输出整数结果"),           # 整数输出
        ("输出描述测试", "统计字符个数，输出统计结果"),             # 描述提取
        ("输出约束测试", "计算平均值，保留2位小数"),               # 精度约束
        ("操作类型测试", "找到数组中的最大值"),                   # 操作识别
        ("复合输出测试", "输出排序后的数组，最多100个元素")         # 复合约束
    ]
    
    for test_name, problem in output_tests:
        print(f"\n{test_name}: {problem}")
        print("-" * 40)
        
        output_format = engine._extract_output_format(problem)
        print(f"  输出类型: {output_format['type']}")
        print(f"  输出描述: {output_format['description']}")
        print(f"  操作类型: {output_format['operation']}")
        
        if output_format['constraints']:
            print(f"  输出约束:")
            for constraint in output_format['constraints']:
                print(f"    {constraint['type']}: {constraint['description']}")
        else:
            print(f"  输出约束: 无")

def demo_json_rule_engine():
    """
    演示JSON规则引擎的完整功能
    
    这个函数展示了规则引擎的核心功能，包括：
    1. 问题分析：关键词匹配、模式匹配、综合评分
    2. 格式提取：输入输出格式和约束条件提取
    3. 解决方案生成：代码模板和测试生成器
    4. 统计信息：规则分布和权重统计
    5. 动态管理：添加关键词和保存规则
    
    通过多个测试用例验证规则引擎的准确性和完整性。
    """
    print("=" * 80)
    print("JSON规则引擎演示")
    print("=" * 80)
    
    # 创建引擎实例
    engine = JSONRuleEngine()
    
    # 测试问题 - 涵盖不同类型的编程问题
    test_problems = [
        "计算两个数的加法",           # 数学运算
        "求阶乘的值",               # 数学函数
        "统计字符串中字母出现次数",    # 字符串处理
        "找到数组中的最大值"         # 数组操作
    ]
    
    for i, problem in enumerate(test_problems, 1):
        print(f"\n问题 {i}: {problem}")
        print("-" * 50)
        
        # 分析问题 - 核心功能演示
        result = engine.analyze_problem(problem)
        
        print(f"问题类型: {result.problem_type}")
        print(f"置信度: {result.confidence:.2%}")
        print(f"匹配的关键词: {result.matched_keywords}")
        print(f"匹配的模式: {result.matched_patterns}")
        print(f"输入格式: {result.input_format}")
        print(f"解决方案模板:\n{result.solution_template}")
    
    # 显示统计信息 - 了解规则库的规模和分布
    print("\n" + "=" * 50)
    print("统计信息")
    print("=" * 50)
    
    stats = engine.get_statistics()
    print(f"总模式数: {stats['total_patterns']}")
    print(f"总关键词数: {stats['total_keywords']}")
    print(f"按类别分布: {stats['patterns_by_category']}")
    print(f"权重分布: {stats['weight_distribution']}")
    
    # 演示动态添加关键词 - 展示规则管理功能
    print("\n" + "=" * 50)
    print("动态添加关键词演示")
    print("=" * 50)
    
    print("添加关键词 'plus' 到 'addition' 模式...")
    engine.add_keyword("addition", "plus", 6)
    
    print("测试新关键词...")
    result = engine.analyze_problem("计算两个数的plus")
    print(f"问题类型: {result.problem_type}")
    print(f"匹配的关键词: {result.matched_keywords}")
    
    # 保存规则 - 持久化动态修改的规则
    print("\n保存规则到文件...")
    engine.save_rules()

if __name__ == "__main__":
    """
    主程序入口
    
    当直接运行此文件时，会依次执行以下演示：
    1. 约束条件提取演示 - 展示输入输出格式提取功能
    2. 完整规则引擎演示 - 展示规则引擎的所有核心功能
    
    这些演示帮助用户了解规则引擎的能力和使用方法。
    """
    # 运行约束条件提取演示 - 展示格式提取和约束识别功能
    demo_constraint_extraction()
    
    print("\n" + "=" * 80)
    print("完整规则引擎演示")
    print("=" * 80)
    
    # 运行完整规则引擎演示 - 展示所有核心功能
    demo_json_rule_engine()
